home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / slang / sldisply.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  40.2 KB  |  1,754 lines

  1. /* Copyright (c) 1992, 1995 John E. Davis
  2.  * All rights reserved.
  3.  * 
  4.  * You may distribute under the terms of either the GNU General Public
  5.  * License or the Perl Artistic License.
  6.  */
  7. #include <config.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <time.h>
  11.  
  12. #include "slang.h"
  13. #include "_slang.h"
  14.  
  15. #ifndef NO_STDLIB_H
  16. #include <stdlib.h>
  17. #endif
  18.  
  19. #ifndef NO_UNISTD_H
  20. # include <unistd.h>
  21. #endif
  22.  
  23. #ifdef __DECC
  24. /* These get prototypes for write an sleep */
  25. /* # include <unixio.h> */
  26. # include <signal.h>
  27. #endif
  28.  
  29. #include <termios.h>
  30.  
  31. #include <sys/ioctl.h>
  32.  
  33. #ifdef linux_unicode
  34. #include <linux/kd.h>
  35. #endif
  36.  
  37. /* Colors:  These definitions are used for the display.  However, the 
  38.  * application only uses object handles which get mapped to this
  39.  * internal representation.  The mapping is performed by the Color_Map
  40.  * structure below. */
  41.  
  42. #define CHAR_MASK    0x000000FF
  43. #define FG_MASK        0x0000FF00
  44. #define BG_MASK        0x00FF0000
  45. #define ATTR_MASK    0x1F000000
  46. #define BGALL_MASK    0x0FFF0000
  47.  
  48. /* The 0x10000000 bit represents the alternate character set.  BGALL_MASK does
  49.  * not include this attribute.
  50.  */
  51.  
  52.  
  53.  
  54. #define GET_FG(color) ((color & FG_MASK) >> 8)
  55. #define GET_BG(color) ((color & BG_MASK) >> 16)
  56. #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
  57.  
  58. int SLtt_Screen_Cols;
  59. int SLtt_Screen_Rows;
  60. int SLtt_Term_Cannot_Insert;
  61. int SLtt_Term_Cannot_Scroll;
  62. int SLtt_Use_Ansi_Colors;
  63. int SLtt_Blink_Mode = 1;
  64. int SLtt_Use_Blink_For_ACS = 0;
  65. int SLtt_Newline_Ok = 0;
  66. int SLtt_Has_Alt_Charset = 0;
  67. int SLtt_Unicode = 0;
  68. int SLtt_DefaultUnicode = 0;
  69.  
  70. static int Automatic_Margins;
  71. /* static int No_Move_In_Standout; */
  72. static int Worthless_Highlight;
  73.  
  74. static int Linux_Console;
  75.  
  76. static int is_xterm;
  77.  
  78. /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
  79.  * is used to indicate a character from the ACS (alt char set).  The exception
  80.  * to this rule is if SLtt_Use_Blink_For_ACS is true.  This means that of 
  81.  * the highbit is set, we interpret that as a blink character.  This is 
  82.  * exploited by DOSemu.
  83.  */
  84. #define JMAX_COLORS 256
  85. #define JNORMAL_COLOR 0
  86.  
  87. typedef struct 
  88. {
  89.    SLtt_Char_Type fgbg;
  90.    SLtt_Char_Type mono;
  91.    char *custom_esc;
  92. } Ansi_Color_Type;
  93.  
  94. #define RGB1(r, g, b)   ((r) | ((g) << 1) | ((b) << 2))
  95. #define RGB(r, g, b, br, bg, bb)  ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
  96.  
  97. static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] = 
  98. {
  99.    {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL},
  100.    {RGB(0, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL},
  101.    {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
  102.    {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
  103.    {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
  104.    {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
  105.    {RGB(0, 0, 1, 0, 1, 0), SLTT_REV_MASK, NULL},
  106.    {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
  107.    {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
  108.    {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
  109.    {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
  110.    {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  111.    {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
  112.    {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
  113.    {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  114.    {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  115.    {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  116.    {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
  117. };
  118.  
  119.  
  120. /* This is the string to use to use when outputting color information.
  121.  */
  122. #ifdef M_UNIX
  123. /* work around for sco console bug that can't handle combined sequences */
  124.   static char *Color_Escape_Sequence = "\033[3%dm\033[4%dm";
  125. #else
  126.   static char *Color_Escape_Sequence = "\033[3%d;4%dm";
  127. #endif
  128.  
  129. char *SLtt_Graphics_Char_Pairs;           /* ac termcap string -- def is vt100 */
  130.  
  131.    
  132. /* 1 if terminal lacks the ability to do into insert mode or into delete
  133.    mode. Currently controlled by S-Lang but later perhaps termcap. */
  134.  
  135. static char *UnderLine_Vid_Str;
  136. static char *Blink_Vid_Str;
  137. static char *Bold_Vid_Str;
  138. static char *Ins_Mode_Str; /* = "\033[4h"; */   /* ins mode (im) */
  139. static char *Eins_Mode_Str; /* = "\033[4l"; */  /* end ins mode (ei) */
  140. static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
  141. static char *Cls_Str; /* = "\033[2J\033[H"; */  /* cl termcap STR  for ansi terminals */
  142. static char *Rev_Vid_Str; /* = "\033[7m"; */    /* mr,so termcap string */
  143. static char *Norm_Vid_Str; /* = "\033[m"; */   /* me,se termcap string */
  144. static char *Del_Eol_Str; /* = "\033[K"; */           /* ce */
  145. static char *Del_Char_Str; /* = "\033[P"; */   /* dc */
  146. static char *Del_N_Lines_Str; /* = "\033[%dM"; */  /* DL */
  147. static char *Add_N_Lines_Str; /* = "\033[%dL"; */  /* AL */
  148. static char *Rev_Scroll_Str;
  149. static char *Curs_Up_Str;
  150. static char *Curs_F_Str;    /* RI termcap string */
  151. static char *Cursor_Visible_Str;    /* vs termcap string */
  152. static char *Cursor_Invisible_Str;    /* vi termcap string */
  153.  
  154. static char *Start_Alt_Chars_Str;  /* as */
  155. static char *End_Alt_Chars_Str;   /* ae */
  156. static char *Enable_Alt_Char_Set;  /* eA */
  157.  
  158. static char *Term_Init_Str;
  159. static char *Term_Reset_Str;
  160.  
  161. /* static int Len_Curs_F_Str = 5; */
  162.  
  163. /* cm string has %i%d since termcap numbers columns from 0 */
  164. /* char *CURS_POS_STR = "\033[%d;%df";  ansi-- hor and vert pos */
  165. static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/   /* cm termcap string */
  166.  
  167.  
  168. /* scrolling region */
  169. static int Scroll_r1 = 0, Scroll_r2 = 23;
  170. static int Cursor_r, Cursor_c;           /* 0 based */
  171.  
  172. /* current attributes --- initialized to impossible value */
  173. static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFF;
  174.  
  175. static int Cursor_Set;               /* 1 if cursor position known, 0
  176.                     * if not.  -1 if only row is known
  177.                     */
  178.  
  179.  
  180. #define MAX_OUTPUT_BUFFER_SIZE 4096
  181.  
  182. static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
  183. static unsigned char *Output_Bufferp = Output_Buffer;
  184.  
  185. unsigned long SLtt_Num_Chars_Output;
  186.  
  187. int SLtt_flush_output (void)
  188. {
  189.    int nwrite = 0;
  190.    int n = (int) (Output_Bufferp - Output_Buffer);
  191.    
  192.    SLtt_Num_Chars_Output += n;
  193.    
  194.    while (n > 0)
  195.      {
  196.     nwrite = write (fileno(stdout), (char *) Output_Buffer + nwrite, n);
  197.     if (nwrite == -1)
  198.       {
  199.          nwrite = 0;
  200. #ifdef EAGAIN
  201.          if (errno == EAGAIN) continue;
  202. #endif
  203. #ifdef EINTR
  204.          if (errno == EINTR) continue;
  205. #endif
  206.          break;
  207.       }
  208.     n -= nwrite;
  209.      }
  210.    Output_Bufferp = Output_Buffer;
  211.    return n;
  212. }
  213.  
  214.  
  215. int SLtt_Baud_Rate;
  216. static void tt_write(char *str, int n)
  217. {
  218.    static unsigned long last_time;
  219.    static int total;
  220.    unsigned long now;
  221.    int ndiff;
  222.    
  223.    if ((str == NULL) || (n <= 0)) return;
  224.    total += n;
  225.    
  226.    while (1)
  227.      {
  228.     ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
  229.     if (ndiff < n)
  230.       {
  231.          MEMCPY ((char *) Output_Bufferp, (char *) str, ndiff);
  232.          Output_Bufferp += ndiff;
  233.          SLtt_flush_output ();
  234.          n -= ndiff;
  235.          str += ndiff;
  236.       }
  237.     else 
  238.       {
  239.          MEMCPY ((char *) Output_Bufferp, str, n);
  240.          Output_Bufferp += n;
  241.          break;
  242.       }
  243.      }
  244.    
  245.    if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
  246.        && (10 * total > SLtt_Baud_Rate))
  247.      {
  248.     total = 0;
  249.     if ((now = (unsigned long) time(NULL)) - last_time <= 1)
  250.       {
  251.          SLtt_flush_output ();
  252.          sleep((unsigned) 1);
  253.       }
  254.     last_time = now;
  255.      }
  256. }
  257.  
  258.  
  259. void SLtt_write_string(char *str)
  260. {
  261.    if (str != NULL) tt_write(str, strlen(str));
  262. }
  263.  
  264.  
  265. void SLtt_putchar(char ch)
  266. {
  267.    SLtt_normal_video ();
  268.    if (Cursor_Set == 1)
  269.      {
  270.     if (ch >= ' ') Cursor_c++;
  271.     else if (ch == '\b') Cursor_c--;
  272.     else if (ch == '\r') Cursor_c = 0;
  273.     else Cursor_Set = 0;
  274.     
  275.     if ((Cursor_c + 1 == SLtt_Screen_Cols) 
  276.         && Automatic_Margins) Cursor_Set = 0;
  277.      }
  278.    
  279.    if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
  280.      {
  281.     *Output_Bufferp++ = (unsigned char) ch;
  282.      }
  283.    else tt_write (&ch, 1);
  284. }
  285.  
  286. /* this is supposed to be fast--- also handles 
  287.    termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
  288. static int tt_sprintf(char *buf, char *fmt, int x, int y)
  289. {
  290.    register unsigned char *f = (unsigned char *) fmt, *b, ch;
  291.    int offset = 0, tinfo = 0;
  292.    int stack[10];
  293.    int i = 0, z;
  294.    stack[0] = y; stack[1] = x; i = 2;
  295.    
  296.    b = (unsigned char *) buf;
  297.    if (fmt != NULL) while ((ch = *f++) != 0)
  298.      {
  299.     if (ch != '%') *b++ = ch;
  300.     else 
  301.       {
  302.          ch = *f++;
  303.          if (tinfo)
  304.            {
  305.           if ((ch <= '3') && (ch >= '0'))
  306.             {
  307.                /* map it to termcap.  Since this is terminfo,
  308.             * it must be one of:
  309.             *   %2d, %3d, %02d, %03d
  310.             * 
  311.             * I am assuming that a terminal that understands
  312.             * %2d form will also understand the %02d form.  These
  313.             * only differ by a space padding the field.
  314.             */
  315.                
  316.                /* skip the 'd'-- hope it is there */
  317.                if (ch == '0') 
  318.              {
  319.                 ch = *f;
  320.                 f += 2;
  321.              }
  322.                else f++;
  323.             }
  324.            }
  325.          
  326.          if (ch == 'p')
  327.            {
  328.           tinfo = 1;
  329.           ch = *f++;
  330.           if (ch == '1') stack[i++] = x; else stack[i++] = y;
  331.            }
  332.          else if (ch == '\'')   /* 'x' */
  333.            {
  334.           stack[i++] = *f++;
  335.           f++;
  336.            }
  337.          else if ((ch == 'd') || (ch == '2') || (ch == '3'))
  338.            {
  339.           z = stack[--i];
  340.           z += offset;
  341.           if (z >= 100)
  342.             {
  343.                *b++ = z / 100 + '0';
  344.                z = z % 100;
  345.                goto ten;
  346.             }
  347.           else if (ch == 3) 
  348.             {
  349.                *b++ = '0';
  350.                ch = '2';
  351.             }
  352.           
  353.           if (z >= 10)
  354.             {
  355.                ten:
  356.                *b++ = z / 10 + '0';
  357.                z = z % 10;
  358.             }
  359.           else if (ch == 2) *b++ = '0';
  360.           
  361.           *b++ = z + '0';
  362.            }
  363.          else if (ch == 'i') 
  364.            {
  365.           offset = 1;
  366.            }
  367.          else if (ch == '+')
  368.            {
  369.           if (tinfo) 
  370.             {
  371.                z = stack[--i];
  372.                stack[i-1] += z;
  373.             }
  374.           else
  375.             {
  376.                ch = *f++;
  377.                if ((unsigned char) ch == 128) ch = 0;
  378.                ch = ch + (unsigned char) stack[--i];
  379.                if (ch == '\n') ch++;
  380.                *b++ = ch;
  381.             }
  382.            }
  383.          else if (ch == 'r')
  384.            {
  385.           stack[0] = x;
  386.           stack[1] = y;
  387.            }
  388.          else if ((ch == '.') || (ch == 'c'))
  389.            {
  390.           ch = (unsigned char) stack[--i];
  391.           if (ch == '\n') ch++;
  392.           *b++ = ch;
  393.            }
  394.          else *b++ = ch;
  395.       }
  396.      }
  397.    *b = 0;
  398.    return((int) (b - (unsigned char *) buf));
  399. }
  400.  
  401. static void tt_printf(char *fmt, int x, int y)
  402. {
  403.    char buf[256];
  404.    int n;
  405.    if (fmt == NULL) return;
  406.    n = tt_sprintf(buf, fmt, x, y);
  407.    tt_write(buf, n);
  408. }
  409.  
  410.  
  411. void SLtt_set_scroll_region (int r1, int r2)
  412. {
  413.    Scroll_r1 = r1;
  414.    Scroll_r2 = r2;
  415.    tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
  416.    Cursor_Set = 0;
  417. }
  418.  
  419. void SLtt_reset_scroll_region (void)
  420. {
  421.     SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
  422. }
  423.  
  424. int SLtt_set_cursor_visibility (int show)
  425. {
  426.    if (show) 
  427.      {
  428.     if (Cursor_Visible_Str != NULL) SLtt_write_string (Cursor_Visible_Str);
  429.     else return -1;
  430.     return 0;
  431.      }
  432.    if (Cursor_Invisible_Str != NULL) SLtt_write_string (Cursor_Invisible_Str);
  433.    else return -1;
  434.    return 0;
  435. }
  436.  
  437.    
  438. /* the goto_rc function moves to row relative to scrolling region */
  439. void SLtt_goto_rc(int r, int c)
  440. {
  441.    char *s = NULL;
  442.    int n;
  443.    char buf[6];
  444.    
  445.    if (c < 0)
  446.      {
  447.     c = -c - 1;
  448.     Cursor_Set = 0;
  449.      }
  450.    
  451.    /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
  452.    r += Scroll_r1;
  453.    
  454.    if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
  455.      {
  456.     n = r - Cursor_r;
  457.     if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c) 
  458.         && (Curs_Up_Str != NULL))
  459.       {
  460.          s = Curs_Up_Str;
  461.       }
  462.     else if ((n >= 0) && (n <= 4))
  463.       {
  464.          if ((n == 0) && (Cursor_Set == 1) 
  465.          && ((c > 1) || (c == Cursor_c)))
  466.            {
  467.           if (Cursor_c == c) return;
  468.           if (Cursor_c == c + 1) 
  469.             {
  470.                s = buf;
  471.                *s++ = '\b'; *s = 0;
  472.                s = buf;
  473.             }
  474.            }
  475.          else if (c == 0)
  476.            {
  477.           s = buf;
  478.           if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
  479.           while (n--) *s++ = '\n';
  480. #ifdef VMS
  481.           /* Need to add this after \n to start a new record.  Sheesh. */
  482.           *s++ = '\r';
  483. #endif
  484.           *s = 0;
  485.           s = buf;
  486.            }
  487.          /* Will fail on VMS */
  488. #ifndef VMS
  489.          else if (SLtt_Newline_Ok && (Cursor_Set == 1) && 
  490.               (Cursor_c >= c) && (c + 3 > Cursor_c))
  491.            {
  492.           s = buf;
  493.           while (n--) *s++ = '\n';
  494.           n = Cursor_c - c;
  495.           while (n--) *s++ = '\b';
  496.           *s = 0;
  497.           s = buf;
  498.            }
  499. #endif
  500.       }
  501.      }
  502.    if (s != NULL) SLtt_write_string(s);
  503.    else tt_printf(Curs_Pos_Str, r, c);
  504.    Cursor_c = c; Cursor_r = r;
  505.    Cursor_Set = 1;
  506. }
  507.  
  508. void SLtt_begin_insert (void)
  509. {
  510.    SLtt_write_string(Ins_Mode_Str);
  511. }
  512.  
  513. void SLtt_end_insert (void)
  514. {
  515.    SLtt_write_string(Eins_Mode_Str);
  516. }
  517.  
  518. void SLtt_delete_char (void)
  519. {
  520.    SLtt_normal_video ();
  521.    SLtt_write_string(Del_Char_Str);
  522. }
  523.  
  524. void SLtt_erase_line (void)
  525. {
  526.    char *s;
  527.    
  528.    Current_Fgbg = 0xFFFFFFFF;
  529.    SLtt_write_string("\r");
  530.    Cursor_Set = 1; Cursor_c = 0;
  531.    if (SLtt_Use_Ansi_Colors) s = "\033[0m";
  532.    else s = Norm_Vid_Str;
  533.    SLtt_write_string(s);
  534.    SLtt_del_eol();
  535. }
  536.  
  537. void SLtt_delete_nlines (int n)
  538. {
  539.    int r1, curs;
  540.    char buf[132];
  541.    if (!n) return;
  542.    SLtt_normal_video ();
  543.    if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
  544.    else
  545.    /* get a new terminal */
  546.      {
  547.     r1 = Scroll_r1;
  548.     curs = Cursor_r;
  549.     SLtt_set_scroll_region(curs, Scroll_r2);
  550.     SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
  551.     MEMSET(buf, '\n', n);
  552.     tt_write(buf, n);
  553.     /* while (n--) tt_putchar('\n'); */
  554.     SLtt_set_scroll_region(r1, Scroll_r2);
  555.     SLtt_goto_rc(curs, 0);
  556.      }
  557. }
  558.  
  559. void SLtt_cls (void)
  560. {
  561.    SLtt_normal_video();
  562.    SLtt_reset_scroll_region ();
  563.    SLtt_write_string(Cls_Str);
  564. }
  565.  
  566. void SLtt_reverse_index (int n)
  567. {
  568.    if (!n) return;
  569.    
  570.    SLtt_normal_video();
  571.    if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
  572.    else
  573.      {
  574.     while(n--) SLtt_write_string(Rev_Scroll_Str);
  575.      }
  576. }
  577.  
  578.  
  579. int SLtt_Ignore_Beep = 3;
  580. static char *Visible_Bell_Str;
  581.  
  582. void SLtt_beep (void)
  583. {
  584.    if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
  585.    
  586.    if (SLtt_Ignore_Beep & 0x2)
  587.      {
  588.     if (Visible_Bell_Str != NULL) SLtt_write_string (Visible_Bell_Str);
  589. #ifdef linux
  590.     else if (Linux_Console)
  591.       {
  592.          SLtt_write_string ("\033[?5h");
  593.          SLtt_flush_output ();
  594.          usleep (50000);
  595.          SLtt_write_string ("\033[?5l");
  596.       }
  597. #endif
  598.      }
  599.    SLtt_flush_output ();
  600. }
  601.  
  602. void SLtt_del_eol (void)
  603. {
  604.    if (Current_Fgbg != 0xFFFFFFFF) SLtt_normal_video ();
  605.    SLtt_write_string(Del_Eol_Str);
  606. }
  607.  
  608. typedef struct
  609. {
  610.    char *name;
  611.    SLtt_Char_Type color;
  612. }
  613. Color_Def_Type;
  614.  
  615. static Color_Def_Type Color_Defs[16] =
  616. {
  617.    {"black",        0x00000000},
  618.    {"red",        0x00000100},
  619.    {"green",        0x00000200},
  620.    {"brown",        0x00000300},
  621.    {"blue",        0x00000400},
  622.    {"magenta",        0x00000500},
  623.    {"cyan",        0x00000600},
  624.    {"lightgray",    0x00000700},
  625.    {"gray",        0x00000800},
  626.    {"brightred",    0x00000900},
  627.    {"brightgreen",    0x00000A00},
  628.    {"yellow",        0x00000B00},
  629.    {"brightblue",    0x00000C00},
  630.    {"brightmagenta",    0x00000D00},
  631.    {"brightcyan",    0x00000E00},
  632.    {"white",        0x00000F00}
  633. };
  634.  
  635. void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
  636. {
  637.    if ((obj < 0) || (obj >= JMAX_COLORS))
  638.      {
  639.     return;
  640.      }   
  641.    Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
  642. }
  643.  
  644.  
  645.  
  646. static unsigned char FgBg_Stats[JMAX_COLORS];
  647.  
  648. void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
  649. {
  650.    char *cust_esc;
  651.    
  652.    if ((obj < 0) || (obj >= JMAX_COLORS)) return;
  653.      
  654.    cust_esc = Ansi_Color_Map[obj].custom_esc;
  655.    if (cust_esc != NULL) 
  656.      {
  657.     SLFREE (cust_esc);
  658.     FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
  659.     Ansi_Color_Map[obj].custom_esc = NULL;
  660.      }
  661.    
  662.    Ansi_Color_Map[obj].fgbg = attr;
  663. }
  664.  
  665. void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
  666. {
  667.    if ((obj < 0) || (obj >= JMAX_COLORS)) return;
  668.      
  669.    Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
  670. }
  671.  
  672.  
  673. void SLtt_set_color (int obj, char *what, char *fg, char *bg)
  674. {
  675.    int i;
  676.    SLtt_Char_Type f = 0xFFFFFFFF, g = 0xFFFFFFFF;
  677.    SLtt_Char_Type attr = 0;
  678.    
  679.    if ((obj < 0) || (obj >= JMAX_COLORS))
  680.      {
  681.     return;
  682.      }
  683.    
  684.    i = 0; while (i < 16)
  685.      {
  686.     if (!strcmp(fg, Color_Defs[i].name))
  687.       {
  688.          f = Color_Defs[i].color;
  689.          if (f & 0x800)
  690.            {
  691.           f &= 0x700;
  692.           attr = SLTT_BOLD_MASK;
  693.            }
  694.          
  695.          break;
  696.       }
  697.     i++;
  698.      }
  699.    i = 0; while (i < 16)
  700.      {
  701.     if (!strcmp(bg, Color_Defs[i].name))
  702.       {
  703.          g = Color_Defs[i].color;
  704.          g &= 0x700;
  705.          g = g << 8;
  706.          break;
  707.       }
  708.     i++;
  709.      }
  710.    
  711.    if ((f == 0xFFFFFFFF) || (g == 0xFFFFFFFF) 
  712.        || ((f == g) && (attr == 0)))
  713.      return;
  714.  
  715.    SLtt_set_color_object (obj, f | g | attr);
  716. }
  717.  
  718. void SLtt_set_color_esc (int obj, char *esc)
  719. {
  720.    char *cust_esc;
  721.    SLtt_Char_Type fgbg = 0;
  722.    int i;
  723.    
  724.    if ((obj < 0) || (obj >= JMAX_COLORS))
  725.      {
  726.     return;
  727.      }
  728.    
  729.    cust_esc = Ansi_Color_Map[obj].custom_esc;
  730.    if (cust_esc != NULL) 
  731.      {
  732.     SLFREE (cust_esc);
  733.     FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
  734.      }
  735.    
  736.    cust_esc = (char *) SLMALLOC (strlen(esc) + 1);
  737.    if (cust_esc != NULL) strcpy (cust_esc, esc);
  738.    
  739.    Ansi_Color_Map[obj].custom_esc = cust_esc;
  740.    if (cust_esc == NULL) fgbg = 0;
  741.    else
  742.      {
  743.     /* The whole point of this is to generate a unique fgbg */
  744.     for (i = 0; i < JMAX_COLORS; i++)
  745.       {
  746.          if (FgBg_Stats[i] == 0) fgbg = i;
  747.          
  748.          if (obj == i) continue;
  749.          if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
  750.          if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
  751.            {
  752.           fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
  753.           break;
  754.            }
  755.       }
  756.     FgBg_Stats[fgbg] += 1;
  757.      }
  758.    
  759.    fgbg |= 0x80;
  760.    Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
  761. }
  762.  
  763.  
  764.  
  765. void SLtt_set_alt_char_set (int i)
  766. {
  767.    static int last_i;
  768.    if (SLtt_Has_Alt_Charset == 0) return;
  769.    if (i == last_i) return;
  770.    SLtt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
  771.    last_i = i;
  772. }
  773.  
  774. static void write_attributes (SLtt_Char_Type fgbg)
  775. {
  776.    int bg0, fg0;
  777.    
  778.    if (Worthless_Highlight) return;
  779.    if (fgbg == Current_Fgbg) return;
  780.    
  781.    /* Before spitting out colors, fix attributes */
  782.    if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
  783.      {
  784.     if (Current_Fgbg & ATTR_MASK)
  785.       {
  786.              SLtt_write_string(Norm_Vid_Str);
  787.          /* In case normal video turns off ALL attributes: */
  788.          if (fgbg & SLTT_ALTC_MASK)
  789.            Current_Fgbg &= ~SLTT_ALTC_MASK;
  790.          SLtt_set_alt_char_set (0);
  791.       }
  792.     
  793.     if ((fgbg & SLTT_ALTC_MASK) 
  794.         != (Current_Fgbg & SLTT_ALTC_MASK))
  795.       {
  796.          SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
  797.       }
  798.     
  799.     if (fgbg & SLTT_ULINE_MASK) SLtt_write_string (UnderLine_Vid_Str);
  800.     if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
  801.     if (fgbg & SLTT_REV_MASK) SLtt_write_string (Rev_Vid_Str);
  802.     if (fgbg & SLTT_BLINK_MASK)
  803.       {
  804.          /* Someday Linux will have a blink mode that set high intensity
  805.           * background.  Lets be prepared.
  806.           */
  807.          if (SLtt_Blink_Mode) SLtt_write_string (Blink_Vid_Str);
  808.       }
  809.      }
  810.    
  811.    if (SLtt_Use_Ansi_Colors)
  812.      {
  813.     fg0 = (int) GET_FG(fgbg);
  814.     bg0 = (int) GET_BG(fgbg);
  815.     tt_printf(Color_Escape_Sequence, fg0, bg0);
  816.      }
  817.    Current_Fgbg = fgbg;
  818. }
  819.  
  820. static int Video_Initialized;
  821.  
  822. void SLtt_reverse_video (int color)
  823. {
  824.    SLtt_Char_Type fgbg;
  825.    char *esc;
  826.    
  827.    if (Worthless_Highlight) return;
  828.    if ((color < 0) || (color >= JMAX_COLORS)) return;
  829.    
  830.    if (Video_Initialized == 0)
  831.      {
  832.     if (color == JNORMAL_COLOR)
  833.       {
  834.          SLtt_write_string (Norm_Vid_Str);
  835.       }
  836.     else SLtt_write_string (Rev_Vid_Str);
  837.     Current_Fgbg = 0xFFFFFFFF;
  838.     return;
  839.      }
  840.    
  841.    if (SLtt_Use_Ansi_Colors) 
  842.      {
  843.     fgbg = Ansi_Color_Map[color].fgbg;
  844.     if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
  845.       {
  846.          if (fgbg != Current_Fgbg)
  847.            {
  848.           Current_Fgbg = fgbg;
  849.           SLtt_write_string (esc);
  850.           return;
  851.            }
  852.       }
  853.      }
  854.    else fgbg = Ansi_Color_Map[color].mono;
  855.  
  856.    if (fgbg == Current_Fgbg) return;
  857.    write_attributes (fgbg);
  858. }
  859.  
  860.  
  861.  
  862.  
  863. void SLtt_normal_video (void)
  864. {
  865.    SLtt_reverse_video(JNORMAL_COLOR);
  866. }
  867.  
  868. void SLtt_narrow_width (void)
  869. {
  870.     SLtt_write_string("\033[?3l");
  871. }
  872.  
  873. void SLtt_wide_width (void)
  874. {
  875.     SLtt_write_string("\033[?3h");
  876. }
  877.  
  878. /* Highest bit represents the character set. */
  879. #ifdef linux_unicode
  880. #define COLOR_MASK 0x7F0000
  881. #else
  882. #define COLOR_MASK 0x7F00
  883. #endif
  884.  
  885. #ifdef linux_unicode
  886. #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 16)
  887. #else
  888. #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
  889. #endif
  890. /*
  891. #define COLOR_EQS(a, b) \
  892.    (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
  893. */
  894.  
  895. #define COLOR_EQS(a, b) \
  896.    (SLtt_Use_Ansi_Colors \
  897.     ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
  898.     :  (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
  899.  
  900.  
  901. #define CHAR_EQS(a, b) (((a) == (b))\
  902.             || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
  903.                 && COLOR_EQS((a), (b))))
  904.  
  905. #ifdef linux_unicode
  906. /* Kernel doesn't support 32bit Unicode, so there is no reason to convert it */
  907. static char *SLtt_Unicode_UTF (unsigned short ch, char *p)
  908. {
  909.    if (ch < 0x80)
  910.      *p++ = (unsigned char) ch;
  911.    else if (ch < 0x800)
  912.      {
  913.        *p++ = (unsigned char) (0xC0 + (ch >> 6));
  914.        *p++ = (unsigned char) 0x80 + (ch & 0x3f);
  915.      }
  916.    else
  917.      {
  918.        *p++ = (unsigned char) (0xE0 + (ch >> 12));
  919.        *p++ = (unsigned char) 0x80 + ((ch >> 6) & 0x3f);
  920.        *p++ = (unsigned char) 0x80 + (ch & 0x3f);
  921.      }
  922.    return p;
  923. }
  924. #endif
  925.  
  926. static void send_attr_str(SLang_Char_Type *s)
  927. {
  928.    unsigned char out[256], *p;
  929. #ifdef linux_unicode
  930.    unsigned char *q;
  931.    unsigned short ch;
  932. #else
  933.    unsigned char ch;
  934. #endif
  935.    register SLtt_Char_Type attr;
  936.    register SLang_Char_Type sh;
  937.    int color, last_color = -1;
  938.    
  939.    p = out;
  940.    while (0 != (sh = *s++))
  941.      {
  942. #ifdef linux_unicode
  943.         ch = sh & 0xFFFF;
  944.         color = ((int) sh & 0xFF0000) >> 16;
  945. #else
  946.     ch = sh & 0xFF;
  947.     color = ((int) sh & 0xFF00) >> 8;
  948. #endif      
  949.     if (color != last_color)
  950.       {
  951.          if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
  952.          else attr = Ansi_Color_Map[color & 0x7F].mono;
  953.          
  954.          if (color & 0x80) /* alternate char set */
  955.            {
  956.           if (SLtt_Use_Blink_For_ACS)
  957.             {
  958.                if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
  959.             }
  960.           else attr |= SLTT_ALTC_MASK;   
  961.            }
  962.          
  963.          if (attr != Current_Fgbg)
  964.            {
  965.           if ((ch != ' ') ||
  966.               /* it is a space so only consider it different if it
  967.                * has different attributes.
  968.                */
  969.               (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK))
  970.             {
  971.                if (p != out)
  972.              {
  973.                 *p = 0;
  974.                 SLtt_write_string((char *) out);
  975.                 Cursor_c += (int) (p - out);
  976.                 p = out;
  977.              }
  978.                
  979.                if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
  980.              {
  981.                 SLtt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
  982.                            /* Just in case the custom escape sequence screwed up
  983.                             * the alt character set state...
  984.                             */
  985.                            if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
  986.                              SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
  987.                 Current_Fgbg = attr;
  988.              }
  989.                else write_attributes (attr);
  990.                
  991.                last_color = color;
  992.             }
  993.            }
  994.       }
  995. #ifdef linux_unicode
  996.     if (SLtt_Unicode)
  997.       {
  998.         if (p > out + sizeof (out) - 6)
  999.           {
  1000.         *p = 0;
  1001.         SLtt_write_string((char *) out);
  1002.         Cursor_c += (int) (p - out);
  1003.         p = out;
  1004.           }
  1005.         q = SLtt_Unicode_UTF (ch, p);
  1006.         Cursor_c -= (int) (q - p - 1);
  1007.         p = q;
  1008.       }
  1009.     else
  1010. #endif      
  1011.       *p++ = (unsigned char) ch;
  1012.      }
  1013.    *p = 0;
  1014.    if (p != out) SLtt_write_string((char *) out);
  1015.    Cursor_c += (int) (p - out);
  1016. }
  1017.  
  1018. static void forward_cursor (int n, int row)
  1019. {
  1020.    char buf[30];
  1021.    
  1022.    
  1023.    if (n <= 4) 
  1024.      {
  1025.     Cursor_c += n;
  1026.     SLtt_normal_video ();
  1027.     MEMSET (buf, ' ', n);
  1028.     tt_write (buf, n);
  1029.      }
  1030.    else if (Curs_F_Str != NULL)
  1031.      {
  1032.     Cursor_c += n;
  1033.     n = tt_sprintf(buf, Curs_F_Str, n, 0);
  1034.     tt_write(buf, n);
  1035.      }
  1036.    else SLtt_goto_rc (row, Cursor_c + n);
  1037. }
  1038.  
  1039. #ifdef linux_unicode
  1040. #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 16))
  1041. #else
  1042. #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
  1043. #endif
  1044.  
  1045. void SLtt_smart_puts(SLang_Char_Type *neww, SLang_Char_Type *oldd, int len, int row)
  1046. {
  1047.    register SLang_Char_Type *p, *q, *qmax, *pmax, *buf;
  1048.    SLang_Char_Type buffer[256];
  1049.    int n_spaces;
  1050.    SLang_Char_Type *space_match, *last_buffered_match;
  1051.    
  1052.    q = oldd; p = neww;
  1053.    qmax = oldd + len;
  1054.    pmax = p + len;
  1055.    
  1056.    /* Find out where to begin --- while they match, we are ok */
  1057.    for (;;)
  1058.      {
  1059.     if (q == qmax) return;
  1060.     if (!CHAR_EQS(*q, *p)) break;
  1061.     q++; p++;
  1062.      }
  1063.  
  1064.    /*position the cursor */
  1065.    SLtt_goto_rc (row, (int) (p - neww));
  1066.  
  1067.    /* Find where the last non-blank character on old/new screen is */
  1068.    
  1069.    while (qmax > q)
  1070.      {
  1071.     qmax--;
  1072.     if (!CHAR_EQS(*qmax, SPACE_CHAR)) 
  1073.       {
  1074.          qmax++;
  1075.          break;
  1076.       }
  1077.      }
  1078.    
  1079.    while (pmax > p)
  1080.      {
  1081.     pmax--;
  1082.     if (!CHAR_EQS(*pmax, SPACE_CHAR))
  1083.       {
  1084.          pmax++;
  1085.          break;
  1086.       }
  1087.      }
  1088.    
  1089.    
  1090.    last_buffered_match = buf = buffer;               /* buffer is empty */
  1091.    
  1092.    /* loop using overwrite then skip algorithm until done */
  1093.    while (1)
  1094.      {
  1095.     /* while they do not match and we do not hit a space, buffer them up */
  1096.     n_spaces = 0;
  1097.     while (p < pmax)
  1098.       {
  1099.          if (CHAR_EQS(*q,SPACE_CHAR) && CHAR_EQS(*p, SPACE_CHAR))
  1100.            {
  1101.           /* If *q is not a space, we would have to overwrite it.  
  1102.            * However, if *q is a space, then while *p is also one, 
  1103.            * we only need to skip over the blank field.
  1104.            */
  1105.           space_match = p;
  1106.           p++; q++;
  1107.           while ((p < pmax) 
  1108.              && CHAR_EQS(*q,SPACE_CHAR) 
  1109.              && CHAR_EQS(*p, SPACE_CHAR))
  1110.             {
  1111.                p++;
  1112.                q++;
  1113.             }
  1114.           n_spaces = (int) (p - space_match);
  1115.           break;
  1116.            }
  1117.          if (CHAR_EQS(*q, *p)) break;
  1118.          *buf++ = *p++;
  1119.          q++;
  1120.       }
  1121.     *buf = 0;
  1122.     
  1123.     if (buf != buffer) send_attr_str (buffer);
  1124.     buf = buffer;
  1125.     
  1126.     if (n_spaces && (p < pmax)) 
  1127.       {
  1128.          forward_cursor (n_spaces, row);
  1129.       }
  1130.     
  1131.     /* Now we overwrote what we could and cursor is placed at position 
  1132.      * of a possible match of new and old.  If this is the case, skip 
  1133.      * some more.
  1134.      */
  1135.     
  1136.     while ((p < pmax) && CHAR_EQS(*p, *q))
  1137.       {
  1138.          *buf++ = *p++;
  1139.          q++;
  1140.       }
  1141.     
  1142.     last_buffered_match = buf;
  1143.     if (p >= pmax) break;
  1144.     
  1145.     /* jump to new position is it is greater than 5 otherwise
  1146.      * let it sit in the buffer and output it later.
  1147.      */
  1148.     if ((int) (buf - buffer) >= 5) 
  1149.       {
  1150.          forward_cursor (buf - buffer, row);
  1151.          last_buffered_match = buf = buffer;
  1152.       }
  1153.      }
  1154.    if (buf != buffer)
  1155.      {
  1156.     if (q < qmax)
  1157.       {
  1158.          if ((buf == last_buffered_match) 
  1159.          && ((int) (buf - buffer) >= 5))
  1160.            {
  1161.           forward_cursor (buf - buffer, row);
  1162.            }
  1163.          else
  1164.            {
  1165.           *buf = 0;
  1166.           send_attr_str (buffer);
  1167.            }
  1168.       }
  1169.      }
  1170.    if (q < qmax) SLtt_del_eol ();
  1171.    if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
  1172. }  
  1173.  
  1174.  
  1175. /* termcap stuff */
  1176.  
  1177. #ifndef unix
  1178. #define unix
  1179. #endif
  1180.  
  1181. #ifdef unix
  1182. #define EXTERN extern
  1183.  
  1184. #ifndef USE_TERMCAP
  1185. static char *Tbuf;
  1186. static char *Tstr_Buf;
  1187.  
  1188. #define tgetstr SLtt_tigetstr
  1189. #define tgetent SLtt_tigetent
  1190. #define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
  1191. #define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
  1192.  
  1193. #else
  1194.  
  1195. EXTERN char *tgetstr(char *, char **);
  1196. EXTERN int tgetent(char *, char *);
  1197. EXTERN int tgetnum(char *);
  1198. EXTERN int tgetflag(char *);
  1199. static char Tstr_Buf[1024];
  1200. static char Tbuf[4096];
  1201. #define TGETNUM tgetnum
  1202. #define TGETFLAG tgetflag
  1203. #endif
  1204.  
  1205. static char *my_tgetstr(char *what, char **p)
  1206. {
  1207.    register char *w, *w1;
  1208.    char *wsave;
  1209.    what = tgetstr(what, p);
  1210.    if (what != NULL)
  1211.      {
  1212.     /* lose pad info --- with today's technology, term is a loser if
  1213.        it is really needed */
  1214.     while ((*what == '.') || 
  1215.            ((*what >= '0') && (*what <= '9'))) what++;
  1216.     if (*what == '*') what++;    
  1217.     
  1218.     /* lose terminfo padding--- looks like $<...> */
  1219.         w = what;
  1220.     while (*w) if ((*w++ == '$') && (*w == '<'))
  1221.       {
  1222.          w1 = w - 1;
  1223.          while (*w && (*w != '>')) w++;
  1224.          if (*w == 0) break;
  1225.          w++;
  1226.          wsave = w1;
  1227.          while ((*w1++ = *w++) != 0);
  1228.          w = wsave;
  1229.       }
  1230.     if (*what == 0) what = NULL; 
  1231.      }
  1232.    return(what);
  1233. }
  1234.  
  1235. char *SLtt_tgetstr (char *s)
  1236. {
  1237. #ifdef USE_TERMCAP
  1238.    static
  1239. #endif
  1240.      char *p = Tstr_Buf;
  1241.    return my_tgetstr (s, &p);
  1242. }
  1243.  
  1244. int SLtt_tgetnum (char *s)
  1245. {
  1246.    return TGETNUM (s);
  1247. }
  1248. int SLtt_tgetflag (char *s)
  1249. {
  1250.    return TGETFLAG (s);
  1251. }
  1252.  
  1253.  
  1254. static int Vt100_Like = 0;
  1255.  
  1256. void SLtt_get_terminfo (void)
  1257. {
  1258.    char *term, *t, ch;
  1259.    static int been_here;
  1260.  
  1261. #ifdef TIOCGWINSZ
  1262.    struct winsize size;
  1263.  
  1264.    if (ioctl (0, TIOCGWINSZ, &size) == 0){
  1265.        if (size.ws_row && size.ws_col){
  1266.        SLtt_Screen_Cols = size.ws_col;
  1267.        SLtt_Screen_Rows = size.ws_row;
  1268.        }
  1269.    }
  1270. #endif
  1271.    
  1272.    if (been_here)
  1273.        return;
  1274.    else
  1275.        been_here = 1;
  1276.    
  1277.    SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
  1278.  
  1279.    if (NULL == (term = (char *) getenv("TERM")))
  1280.      {
  1281.     SLang_exit_error("TERM environment variable needs set.");
  1282.      }
  1283.    
  1284.    Linux_Console = (!strncmp (term, "linux", 5)
  1285. #ifdef linux
  1286.        || (!strncmp(term, "con", 3))
  1287. #endif
  1288.       );
  1289.    
  1290.    t = term;
  1291.    
  1292.    if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
  1293.        && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1; 
  1294.  
  1295. #ifndef USE_TERMCAP
  1296.    if (NULL == (Tbuf = tgetent (term))) 
  1297.      {
  1298.     char err_buf[512];
  1299.     /* Special cases. */
  1300.     if (Vt100_Like
  1301.         || Linux_Console
  1302.         || !strcmp (term, "screen"))
  1303.       {
  1304.          int vt102 = 1;
  1305.          if (!strcmp (term, "vt100")) vt102 = 0;
  1306.  
  1307.          if (!(SLtt_Screen_Cols || SLtt_Screen_Rows)){
  1308.          SLtt_Screen_Cols = 80;
  1309.          SLtt_Screen_Rows = 24;
  1310.          }
  1311.          if (Linux_Console) SLtt_Screen_Rows++;
  1312.             SLtt_set_term_vtxxx (&vt102);
  1313.          return;
  1314.       }
  1315.     sprintf (err_buf, "Unknown terminal: %s\n\
  1316. Check the TERM environment variable.\n\
  1317. Also make sure that the terminal is defined in the terminfo database.\n\
  1318. Alternatively, set the TERMCAP environment variable to the desired\n\
  1319. termcap entry.", term);
  1320.     SLang_exit_error(err_buf);
  1321.      }
  1322.    Tstr_Buf = Tbuf;
  1323. #else                       /* USE_TERMCAP */
  1324.    if (1 != tgetent(Tbuf, term)) SLang_exit_error("Unknown terminal.");
  1325. #endif                       /* NOT USE_TERMCAP */
  1326.    
  1327.    if ((NULL == (Cls_Str = SLtt_tgetstr("cl"))) 
  1328.        || (NULL == (Curs_Pos_Str = SLtt_tgetstr("cm"))))
  1329.      {
  1330.     SLang_exit_error("Terminal not powerful enough for SLang.");
  1331.      }
  1332.    
  1333.    if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
  1334.        || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
  1335.        || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
  1336.      SLtt_Term_Cannot_Insert = 1;
  1337.    
  1338.    Visible_Bell_Str = SLtt_tgetstr ("vb");
  1339.    Curs_Up_Str = SLtt_tgetstr ("up");
  1340.    Rev_Scroll_Str = SLtt_tgetstr("sr");
  1341.    Del_N_Lines_Str = SLtt_tgetstr("DL");
  1342.    Add_N_Lines_Str = SLtt_tgetstr("AL");
  1343.    
  1344.    /* Actually these are used to initialize terminals that use cursor 
  1345.     * addressing.  Hard to believe.
  1346.     */
  1347.    Term_Init_Str = SLtt_tgetstr ("ti");
  1348.    Term_Reset_Str = SLtt_tgetstr ("te");
  1349.    
  1350.    /* Make up for defective termcap/terminfo databases */
  1351.    if ((Vt100_Like && (term[2] != '1'))
  1352.        || Linux_Console
  1353.        )
  1354.      {
  1355.     if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
  1356.     if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
  1357.      }
  1358.    
  1359.    Scroll_R_Str = SLtt_tgetstr("cs");
  1360.    
  1361.    if ((SLtt_Screen_Rows == 0) || (SLtt_Screen_Cols == 0))
  1362.      {
  1363.     char *envptr;
  1364.     if ((SLtt_Screen_Cols = TGETNUM("co")) <= 0) SLtt_Screen_Cols = 80;
  1365.     if ((SLtt_Screen_Rows = TGETNUM("li")) <= 0) SLtt_Screen_Rows = 24;
  1366.     envptr = getenv ("LINES");
  1367.     if (envptr != NULL)
  1368.       {
  1369.          if ((SLtt_Screen_Rows = atoi (envptr)) <= 0) 
  1370.            SLtt_Screen_Rows = 24;
  1371.       }
  1372.     
  1373.     envptr = getenv ("COLUMNS");
  1374.     if (envptr != NULL)
  1375.       {
  1376.          if ((SLtt_Screen_Cols = atoi (envptr)) <= 0) 
  1377.            SLtt_Screen_Cols = 80;
  1378.       }
  1379.      }
  1380.    
  1381.    is_xterm = (!strncmp (term, "xterm", 5) || !strcmp (term, "vs100"));
  1382.    
  1383.    if ((Scroll_R_Str == NULL) 
  1384.        || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
  1385.        && (NULL == Rev_Scroll_Str)))
  1386.      {
  1387.     if (is_xterm)
  1388.       {
  1389.          /* Defective termcap mode!!!! */
  1390.          SLtt_set_term_vtxxx (&is_xterm);
  1391.       }
  1392.     else SLtt_Term_Cannot_Scroll = 1;
  1393.      }
  1394.    
  1395.    Del_Eol_Str = SLtt_tgetstr("ce");
  1396.  
  1397.    Rev_Vid_Str = SLtt_tgetstr("mr");
  1398.    if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
  1399.    
  1400.    Bold_Vid_Str = SLtt_tgetstr("md");
  1401.    Blink_Vid_Str = SLtt_tgetstr("mb");
  1402.    UnderLine_Vid_Str = SLtt_tgetstr("us");
  1403.    
  1404.    Start_Alt_Chars_Str = SLtt_tgetstr ("as");   /* smacs */
  1405.    End_Alt_Chars_Str = SLtt_tgetstr ("ae");   /* rmacs */
  1406.    Enable_Alt_Char_Set = SLtt_tgetstr ("eA");   /* enacs */
  1407.    SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
  1408.    
  1409.    /* I have had it with defective console/linux terminfo entries provided 
  1410.     * by ncurses.  They are not reliable.  I cannot track every ncurses 
  1411.     * release and fudge my stuff to work with defective stuff.  For that
  1412.     * reason, I am hardcoding some things.
  1413.     */
  1414.    if (Linux_Console)
  1415.      {
  1416. #if 0
  1417.        char *lgcp = "l\332m\300k\277j\331u\264t\303v\301w\302q\304x\263n\053o\176s\137`\004a\260f\370g\361~\011,\020+\021.\031-\030h\261i\0250\333";
  1418.  
  1419.        if ((SLtt_Graphics_Char_Pairs == NULL)
  1420.            || (0 == strncmp (SLtt_Graphics_Char_Pairs, lgcp, 8)))
  1421.          {
  1422.             Start_Alt_Chars_Str = "\033(B\033)U\016";
  1423.             End_Alt_Chars_Str = "\033(B\033)0\017";
  1424.             Enable_Alt_Char_Set = NULL;
  1425.          }
  1426. #else
  1427.        char *lgcp = "`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o\302q\304r\362s_t\303u\264v\301w\302x\263y\371z\372{\373|\374}\375~";
  1428.  
  1429.        if ((SLtt_Graphics_Char_Pairs == NULL)
  1430.            || (0 == strncmp (SLtt_Graphics_Char_Pairs, lgcp, 16)))
  1431.          {
  1432.             SLtt_Graphics_Char_Pairs = lgcp;
  1433.             Start_Alt_Chars_Str = "\033[11m";
  1434.             End_Alt_Chars_Str = "\033[10m";
  1435.             Enable_Alt_Char_Set = NULL;
  1436.          }
  1437. #endif
  1438.      }
  1439.    else if (NULL == SLtt_Graphics_Char_Pairs)
  1440.      {
  1441.     /* make up for defective termcap/terminfo */
  1442.     if (Vt100_Like)
  1443.       {
  1444.          Start_Alt_Chars_Str = "\016";
  1445.          End_Alt_Chars_Str = "\017";
  1446.          Enable_Alt_Char_Set = "\033)0";
  1447.       }
  1448.      }
  1449.    
  1450.    if (is_xterm)
  1451.      {
  1452.     Start_Alt_Chars_Str = "\016";
  1453.     End_Alt_Chars_Str = "\017";
  1454.     Enable_Alt_Char_Set = "\033(B\033)0";
  1455.      }
  1456.    
  1457.    if ((SLtt_Graphics_Char_Pairs == NULL) && 
  1458.        ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
  1459.      {
  1460.     SLtt_Has_Alt_Charset = 0;
  1461.     Enable_Alt_Char_Set = NULL;
  1462.      }
  1463.    else SLtt_Has_Alt_Charset = 1;
  1464.    
  1465.        
  1466.    
  1467.    if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me"))) 
  1468.      {
  1469.     Norm_Vid_Str = SLtt_tgetstr("se");
  1470.      }
  1471.    
  1472.    Cursor_Invisible_Str = SLtt_tgetstr("vi");
  1473.    Cursor_Visible_Str = SLtt_tgetstr("vs");
  1474.    
  1475.    Curs_F_Str = SLtt_tgetstr("RI");
  1476.    
  1477. #if 0
  1478.    if (NULL != Curs_F_Str)
  1479.      {
  1480.      Len_Curs_F_Str = strlen(Curs_F_Str);
  1481.      }
  1482.    else Len_Curs_F_Str = strlen(Curs_Pos_Str);
  1483. #endif
  1484.    
  1485.    Automatic_Margins = TGETFLAG ("am");
  1486.    /* No_Move_In_Standout = !TGETFLAG ("ms"); */
  1487.    Worthless_Highlight = TGETFLAG ("xs");
  1488.    
  1489.    if (Worthless_Highlight == 0)
  1490.      {
  1491.     Worthless_Highlight = (TGETNUM ("sg") > 0);
  1492.      }
  1493. }
  1494.  
  1495. #endif
  1496. /* Unix */
  1497.  
  1498. /* specific to vtxxx only */
  1499. void SLtt_enable_cursor_keys (void)
  1500. {
  1501. #ifdef unix
  1502.    if (Vt100_Like ||
  1503. #ifdef linux
  1504.        Linux_Console ||
  1505. #endif
  1506.        is_xterm)
  1507. #endif
  1508.    SLtt_write_string("\033=\033[?1l");
  1509. }
  1510.  
  1511. #ifdef VMS
  1512. void SLtt_get_terminfo ()
  1513. {
  1514.    int zero = 0;
  1515.    SLtt_set_term_vtxxx(&zero);
  1516.    Start_Alt_Chars_Str = "\016";
  1517.    End_Alt_Chars_Str = "\017";
  1518.    SLtt_Has_Alt_Charset = 1;
  1519.    SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
  1520.    Enable_Alt_Char_Set = "\033(B\033)0";    
  1521. }
  1522. #endif
  1523.  
  1524. /* This sets term for vt102 terminals it parameter vt100 is 0.  If vt100
  1525.  * is non-zero, set terminal appropriate for a only vt100  
  1526.  * (no add line capability). */
  1527.                                
  1528. void SLtt_set_term_vtxxx(int *vt100)
  1529. {
  1530.    Norm_Vid_Str = "\033[m";
  1531.    
  1532.    Scroll_R_Str = "\033[%i%d;%dr"; 
  1533.    Cls_Str = "\033[2J\033[H";
  1534.    Rev_Vid_Str = "\033[7m";
  1535.    Bold_Vid_Str = "\033[1m";
  1536.    Blink_Vid_Str = "\033[5m";
  1537.    UnderLine_Vid_Str = "\033[4m";
  1538.    Del_Eol_Str = "\033[K";
  1539.    Rev_Scroll_Str = "\033M";
  1540.    Curs_F_Str = "\033[%dC";
  1541.    /* Len_Curs_F_Str = 5; */
  1542.    Curs_Pos_Str = "\033[%i%d;%dH";
  1543.    if (*vt100 == 0)
  1544.      {
  1545.     Ins_Mode_Str = "\033[4h";
  1546.     Eins_Mode_Str = "\033[4l";
  1547.     Del_Char_Str =  "\033[P";
  1548.     Del_N_Lines_Str = "\033[%dM";
  1549.     Add_N_Lines_Str = "\033[%dL";
  1550.     SLtt_Term_Cannot_Insert = 0;
  1551.      }
  1552.    else
  1553.      {
  1554.     Del_N_Lines_Str = NULL;
  1555.     Add_N_Lines_Str = NULL;
  1556.     SLtt_Term_Cannot_Insert = 1;
  1557.      }
  1558.    SLtt_Term_Cannot_Scroll = 0;
  1559.    /* No_Move_In_Standout = 0; */
  1560. }
  1561.  
  1562. #ifdef linux_unicode
  1563. static unsigned short unifix[] = {
  1564. SLUNI_DHLINE_CHAR, SLUNI_HLINE_CHAR,
  1565. SLUNI_DVLINE_CHAR, SLUNI_VLINE_CHAR,
  1566. SLUNI_DULCORN_CHAR, SLUNI_ULCORN_CHAR,
  1567. SLUNI_DURCORN_CHAR, SLUNI_URCORN_CHAR,
  1568. SLUNI_DLLCORN_CHAR, SLUNI_LLCORN_CHAR,
  1569. SLUNI_DLRCORN_CHAR, SLUNI_LRCORN_CHAR,
  1570. SLUNI_DRTEE_CHAR, SLUNI_RTEE_CHAR,
  1571. SLUNI_DLTEE_CHAR, SLUNI_LTEE_CHAR,
  1572. SLUNI_DUTEE_CHAR, SLUNI_UTEE_CHAR,
  1573. SLUNI_DDTEE_CHAR, SLUNI_DTEE_CHAR,
  1574. SLUNI_DCROSS_CHAR, SLUNI_CROSS_CHAR,
  1575. SLUNI_HLINE_CHAR, '|',
  1576. SLUNI_VLINE_CHAR, '-',
  1577. SLUNI_ULCORN_CHAR, '+',
  1578. SLUNI_URCORN_CHAR, '+',
  1579. SLUNI_LLCORN_CHAR, '+',
  1580. SLUNI_LRCORN_CHAR, '+',
  1581. SLUNI_RTEE_CHAR, '+',
  1582. SLUNI_LTEE_CHAR, '+',
  1583. SLUNI_UTEE_CHAR, '+',
  1584. SLUNI_DTEE_CHAR, '+',
  1585. SLUNI_CROSS_CHAR, '+',
  1586. SLUNI_DSRTEE_CHAR, SLUNI_RTEE_CHAR,
  1587. SLUNI_DSLTEE_CHAR, SLUNI_LTEE_CHAR,
  1588. SLUNI_DSUTEE_CHAR, SLUNI_UTEE_CHAR,
  1589. SLUNI_DSDTEE_CHAR, SLUNI_DTEE_CHAR,
  1590. SLUNI_SDRTEE_CHAR, SLUNI_RTEE_CHAR,
  1591. SLUNI_SDLTEE_CHAR, SLUNI_LTEE_CHAR,
  1592. SLUNI_SDUTEE_CHAR, SLUNI_UTEE_CHAR,
  1593. SLUNI_SDDTEE_CHAR, SLUNI_DTEE_CHAR,
  1594. SLUNI_CKBRD_CHAR, 'o'
  1595. };
  1596.  
  1597. unsigned short SLtt_fix_unicode (unsigned short ch)
  1598. {
  1599.    int i;
  1600.    
  1601.    for (i = 0; i < sizeof (unifix) / sizeof (unifix [0]); i += 2)
  1602.       if (ch == unifix [i])
  1603.           return unifix [i + 1];
  1604.    return ch;
  1605. }
  1606.  
  1607. int SLtt_unicode_init (void)
  1608. {
  1609.    struct unipair *list = NULL;
  1610.    struct unimapdesc descr;
  1611.    int i, j;
  1612.    
  1613.    descr.entry_ct = 0;
  1614.    descr.entries = 0;
  1615.    if (ioctl(0, GIO_UNIMAP, (unsigned long) &descr))
  1616.       {
  1617.           if (errno != ENOMEM || descr.entry_ct == 0)
  1618.             {
  1619.                SLtt_Unicode = 0;
  1620.                return 0;
  1621.             }
  1622.           descr.entries = list = (struct unipair *) SLMALLOC(descr.entry_ct * 
  1623.                sizeof (struct unipair));
  1624.           if (ioctl (0, GIO_UNIMAP, (unsigned long) &descr))
  1625.             {
  1626.                SLFREE(list);
  1627.                SLtt_Unicode = 0;
  1628.                return 0;
  1629.             }
  1630.       }
  1631.    for (i = 0; i < descr.entry_ct; i++)
  1632.       for (j = 0; j < sizeof (unifix) / sizeof (unifix [0]); j += 2)
  1633.          if (list [i].unicode == unifix [j])
  1634.             {
  1635.                unifix [j + 1] = unifix [j];
  1636.                break;
  1637.             }
  1638.    for (i = 0; i < sizeof (unifix) / sizeof (unifix [0]); i += 2)
  1639.      {
  1640.         if (unifix [i] == unifix [i + 1] || unifix [i + 1] < 127)
  1641.            continue;
  1642.         for (j = 0; j < sizeof (unifix) / sizeof (unifix [0]); j += 2)
  1643.            if (unifix [j] == unifix [i + 1])
  1644.               {
  1645.                  unifix [i + 1] = unifix [j + 1];
  1646.                  break;
  1647.               }
  1648.      }
  1649.    if (list)
  1650.       SLFREE(list);
  1651.    return 1;
  1652. }
  1653. #else /*linux unicode */
  1654. unsigned short SLtt_fix_unicode (unsigned short ch)
  1655. {
  1656.    return ch;
  1657. }
  1658. #endif
  1659.  
  1660. void SLtt_init_video (void)
  1661. {
  1662.    static int last_i;
  1663.    /*   send_string_to_term("\033[?6h"); */
  1664.    /* relative origin mode */
  1665.    last_i = 0;
  1666.    SLtt_write_string (Term_Init_Str);
  1667.    SLtt_reset_scroll_region();
  1668.    SLtt_end_insert();
  1669.    SLtt_write_string (Enable_Alt_Char_Set);
  1670. #ifdef linux_unicode
  1671.    if (!SLtt_Unicode)
  1672.      {
  1673.         char *term = (char *) getenv ("TERM");
  1674.    
  1675.         if (term && (!strncmp(term, "con", 3) || !strncmp (term, "linux", 5)))
  1676.           {
  1677.              term = (char *) getenv ("LC_CTYPE");
  1678.              if (!term) term = (char *) getenv ("LANG");
  1679.              if (term && strchr (term, '8') && 
  1680.                  (strstr (term, "UTF") || strstr (term, "utf")))
  1681.                {
  1682.                   SLtt_Unicode = 1;
  1683.                   SLtt_DefaultUnicode = 1;
  1684.                }
  1685.           }
  1686.      }
  1687.    if (SLtt_Unicode)
  1688.      {
  1689.         if (SLtt_unicode_init ())
  1690.             SLtt_write_string ("\033%8");
  1691.      }
  1692. #endif   
  1693.    Video_Initialized = 1;
  1694. }
  1695.  
  1696. void SLtt_want_unicode (void)
  1697. {
  1698. #ifdef linux_unicode
  1699.    char *term = (char *) getenv ("TERM");
  1700.    
  1701.    if (term)
  1702.       if (!strncmp(term, "con", 3) || !strncmp (term, "linux", 5))
  1703.          SLtt_Unicode = 1;
  1704. #endif
  1705. }
  1706.  
  1707. void SLtt_reset_video (void)
  1708. {
  1709.    SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
  1710.    Cursor_Set = 0;
  1711.    SLtt_normal_video ();           /* MSKermit requires this  */
  1712.    SLtt_write_string(Norm_Vid_Str);
  1713.    Current_Fgbg = 0xFFFFFFFF;
  1714.    SLtt_set_alt_char_set (0);
  1715.    SLtt_write_string ("\n");
  1716.    SLtt_del_eol ();
  1717. #ifdef linux_unicode
  1718.    if (SLtt_Unicode && !SLtt_DefaultUnicode)
  1719.      {
  1720.         SLtt_write_string ("\033%@");
  1721.      }
  1722. #endif   
  1723.    SLtt_write_string (Term_Reset_Str);
  1724.    SLtt_flush_output ();
  1725.    Video_Initialized = 0;
  1726. }
  1727.  
  1728. void SLtt_bold_video (void)
  1729. {
  1730.    SLtt_write_string (Bold_Vid_Str);
  1731. }
  1732.  
  1733. #if 0
  1734. /* Midnight Commandes does not use this */
  1735. int SLtt_set_mouse_mode (int mode, int force)
  1736. {
  1737.    char *term;
  1738.    
  1739.    if (force == 0)
  1740.      {
  1741.        if (NULL == (term = (char *) getenv("TERM"))) return -1;
  1742.        if (strncmp ("xterm", term, 5))
  1743.          return -1;
  1744.      }
  1745.    
  1746.    if (mode)
  1747.      SLtt_write_string ("\033[?9h");
  1748.    else
  1749.      SLtt_write_string ("\033[?9l");
  1750.    
  1751.    return 0;
  1752. }
  1753. #endif
  1754.